package com.netcracker.studportal.server.dao.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.Session;

import com.netcracker.studportal.server.dao.MaterialDAO;
import com.netcracker.studportal.server.model.Exam;
import com.netcracker.studportal.server.model.Material;
import com.netcracker.studportal.server.util.HibernateUtil;

public class MaterialDAOImpl implements MaterialDAO {
	private static final Logger LOG = Logger.getLogger(MaterialDAOImpl.class);

	@Override
	public void Add(Material material) throws Exception {
		Session session = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			// if (material.getId() == null) throw new
			// IllegalArgumentException("Id field can't be null");
			if (material.getExam() == null)
				throw new IllegalArgumentException("Exam field can't be null");
			else if (material.getExam().getId() == null)
				throw new IllegalArgumentException(
						"Exam id field can't be null");

			if (material.getName() == null)
				throw new IllegalArgumentException("Name field can't be null");

			session.beginTransaction();
			session.save(material);
			session.getTransaction().commit();
		} catch (Exception e) {
			LOG.error("Error: ", e);
			// TODO delete it, show errors in log
			e.printStackTrace();
			throw new Exception(e);
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}
	}

	@Override
	public void Update(Material newMaterial) throws Exception {
		Session session = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			if (newMaterial.getId() == null)
				throw new IllegalArgumentException("Id field can't be null");
			Material oldMaterial = (Material) session.load(Material.class, newMaterial.getId());

			if (newMaterial.getExam() == null)
				newMaterial.setExam(oldMaterial.getExam());
			else if (newMaterial.getExam().getId() == null)
				throw new IllegalArgumentException(
						"Exam id field can't be null");

			if (newMaterial.getName() == null)
				newMaterial.setName(oldMaterial.getName());

			if (newMaterial.getPath() == null)
				newMaterial.setPath(oldMaterial.getPath());

			session.clear();
			session.beginTransaction();
			session.update(newMaterial);
			session.getTransaction().commit();
		} catch (Exception e) {
			LOG.error("Error: ", e);
			// TODO delete it, show errors in log
			e.printStackTrace();
			throw new Exception(e);
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}
	}

	@Override
	public Material getById(Long id) throws Exception {
		Session session = null;
		Material material = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			material = (Material) session.load(Material.class, id);
			Hibernate.initialize(material.getExam());
		} catch (Exception e) {
			LOG.error("Error: ", e);
			// TODO delete it, show errors in log
			e.printStackTrace();
			throw new Exception(e);
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}
		return material;
	}

	@Override
	public void Delete(Material material) throws Exception {
		Session session = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			session.beginTransaction();
			session.delete(material);
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception(e);
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}
	}

	@Override
	public Collection<Material> getAll() throws Exception {
		Session session = null;
		List<Material> material = new ArrayList<Material>();
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			material = session.createCriteria(Material.class).list();
		} catch (Exception e) {
			LOG.error("Error: ", e);
			// TODO delete it, show errors in log
			e.printStackTrace();
			throw new Exception(e);
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}
		return material;
	}

	@Override
	public Collection<Material> getMaterialsByExam(Exam ex) throws Exception {
		Session session = null;
		Collection<Material> materials = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			materials = (Collection<Material>) session.createSQLQuery(
							"select * from materials where exam_id=" + ex.getId())
							.addEntity(Material.class).list();
		} catch (Exception e) {
			LOG.error("Error: ", e);
			// TODO delete it, show errors in log
			e.printStackTrace();
			throw new Exception(e);
		} finally {
			if (session != null && session.isOpen()) {
				session.close();
			}
		}
		return materials;
	}

	/**
	 * Realization of singleton.
	 */
	private MaterialDAOImpl() {}
	private static MaterialDAO instance;
	public static MaterialDAO getInstance() {
		if (instance == null) {
			instance = new MaterialDAOImpl();
		}
		return instance;
	}
}
